package com.kly.pay.task;

import com.alibaba.fastjson.JSONObject;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.kly.dto.ProductDto;
import com.kly.enums.PayGatewayEnum;
import com.kly.enums.PayStatusEnum;
import com.kly.enums.PayTypeEnum;
import com.kly.pay.db.dao.PCallbackDao;
import com.kly.pay.db.dao.POrderDao;
import com.kly.pay.db.dao.PPayTaskDao;
import com.kly.pay.db.entity.PCallbackEntity;
import com.kly.pay.db.entity.POrderEntity;
import com.kly.pay.db.entity.PPayTaskEntity;
import com.kly.req.RepayRequest;
import com.kly.rsp.RepayResponse;
import com.kly.service.pay.RepayService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author linqu
 */
@Service
public class CallBackTaskService {

    private static final Log logger = LogFactory.getLog(CallBackTaskService.class);

    public static final long EFFECTIVE_IN_1_HOURS = (long) 60 * 60;

    @Resource
    PPayTaskDao payTaskDao;
    @Resource
    PCallbackDao callbackDao;
    @Resource
    POrderDao orderDao;
    @Resource
    RedisClient redisClient;
    @Resource
    RepayService repayService;

    private final static String CALLBACK_KEY = "ck_{}_{}";

    public static Map<PayTypeEnum, AbstractCallBackSendService> handlers = new HashMap<>();


    public void syncCallBack() {


        final List<PPayTaskEntity> pPayTaskEntities = payTaskDao.queryProcessingTask();
        if (CollectionUtils.isEmpty(pPayTaskEntities)) {
            return;
        }
        for (PPayTaskEntity entity : pPayTaskEntities) {
            try {
                final POrderEntity payOrder = orderDao.queryByPayOrderNoAndPayType(entity.getPayOrderNo(), String.valueOf(entity.getPayType()));
                if (Objects.nonNull(payOrder) && StringUtils.isNotBlank(payOrder.getCallbackUrl())) {
                    final PayTypeEnum payTypeEnum = PayTypeEnum.getEnumByCode(entity.getPayType());
                    if (Objects.isNull(payTypeEnum)) {
                        logger.error("syncCallBack invoker failed-,payOrderNo:{},payType:{},detail:{}", entity.getPayOrderNo(), entity.getPayType(), JSONObject.toJSONString(payOrder));
                        continue;
                    }

                    final CallBackResult callBackResult = doJob(payTypeEnum, payOrder);
                    if (callBackResult.getSuccess()) {
                        entity.setStatus(1);
                    } else {
                        entity.setNextJobTime(getDateMinutesLater(5));
                    }
                    payTaskDao.updateByPrimaryKey(entity);
                }
            } catch (Exception e) {
                logger.info("syncCallBack failed, taskDetail:{}", JSONObject.toJSONString(entity), e);
            }
        }


    }



    private CallBackResult doJob(PayTypeEnum payTypeEnum, POrderEntity payOrder) {
//        final String payOrderPay = redisClient.get(CALLBACK_KEY, String.valueOf(payTypeEnum.getCode()), payOrder.getPayOrderNo());
//        if (StringUtils.isNotBlank(payOrderPay)) {
//            return;
//        }
        CallBackResult callBackResult = null;
        try {
            // 发起调用
            callBackResult = handlers.get(payTypeEnum).doCallBack(payTypeEnum, payOrder);
            // 保存本次调用结果
            addPCallbackHistory(payOrder, callBackResult);
            return callBackResult;

        } catch (Exception e) {
            callBackResult = new CallBackResult("CallBackTaskService.InvokerCallBack error", false, "", "");
            addPCallbackHistory(payOrder, callBackResult);
            //回调异常，受理号标记
            logger.error("CallBackTaskService.InvokerCallBack error-, payOrderNo:{},payType:{},detail:{}", payOrder.getPayOrderNo(), payOrder.getPayType(), JSONObject.toJSONString(payOrder), e);
            return callBackResult;
        }
    }


    private RepayRequest buildRepayRequest(POrderEntity payOrder) {


        final RepayRequest repayRequest = RepayRequest.builder().orderNo(payOrder.getOrderNo())
                .productCode(payOrder.getProductCode()).userCode(payOrder.getUserCode())
                .payType(String.valueOf(PayTypeEnum.REPAY.getCode()))
                .callbackUrl(payOrder.getCallbackUrl())
                .payExt(payOrder.getPayExt()).build();

        if (Objects.nonNull(payOrder.getAmount())) {
            repayRequest.setAmount(payOrder.getAmount().toString());
        }
        repayRequest.setPayGateway(PayGatewayEnum.GOOGLE_PAY.getCode());

        return repayRequest;
    }


    public void addPCallbackHistory(POrderEntity paymentInfo, CallBackResult callBackResult) {
        if (null == callBackResult) {
            return;
        }
        //查看最近一次回调
        List<PCallbackEntity> pLastCallbackHistoryList = callbackDao.queryLastRecords(paymentInfo.getPayOrderNo());
        int callbackTimes = 1;
        if (null != pLastCallbackHistoryList && pLastCallbackHistoryList.size() > 0) {
            for (PCallbackEntity pCallbackHistoryEntity : pLastCallbackHistoryList) {
                pCallbackHistoryEntity.setDeleted(true);
                callbackDao.updateByPrimaryKey(pCallbackHistoryEntity);
            }
            callbackTimes = pLastCallbackHistoryList.get(0).getCallbackTimes() + 1;
        }
        PCallbackEntity pCallbackHistoryEntity = new PCallbackEntity();
        pCallbackHistoryEntity.setPayOrderNo(paymentInfo.getPayOrderNo());
        pCallbackHistoryEntity.setOrderNo(paymentInfo.getOrderNo());
        pCallbackHistoryEntity.setCallbackParaContent(callBackResult.getCallBackMsg());
        pCallbackHistoryEntity.setCallbackStatus(callBackResult.getSuccess());
        if (!callBackResult.getSuccess()) {
            pCallbackHistoryEntity.setNextTime(getDateMinutesLater(callbackTimes * 2));
        }
        pCallbackHistoryEntity.setCallbackResult(callBackResult.getNotifyMsg());
        pCallbackHistoryEntity.setCallbackTimes(callbackTimes);
        callbackDao.insert(pCallbackHistoryEntity);

        // 设置缓存
        redisClient.set(CALLBACK_KEY, paymentInfo.getPayOrderNo(), EFFECTIVE_IN_1_HOURS, String.valueOf(paymentInfo.getPayType()), paymentInfo.getPayOrderNo());
    }

    public static Date getDateMinutesLater(int minutes) {
        Calendar now = Calendar.getInstance();
        now.add(Calendar.MINUTE, minutes);
        String nowDate = DateUtil.getDate(now.getTime(), "yyyy-MM-dd HH:mm:ss");
        Date date = null;
        try {
            date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(nowDate);
        } catch (ParseException pe) {
        }
        return date;
    }

}
